package com.etnet.streamserver.view.client;

import com.etnet.streamserver.view.Configure;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ConnManager {
    private Logger log = LoggerFactory.getLogger(super.getClass());
    boolean isConnected = false;
    boolean isShutdown = false;
    private Lock unFairLock = new ReentrantLock();
    private String serverip;
    private String serverport;
    private Socket socket = null;
    private DataInputStream in;
    private DataOutputStream out;
    private long interval = 15000L;
    private static ConnManager connManager = new ConnManager();

    public static ConnManager getInstance() {
        return connManager;
    }

    private boolean connect() {
        boolean ret = false;
        this.unFairLock.lock();
        try {
            if (this.socket == null) {
                int port = Integer.parseInt(this.serverport);
                this.socket = new Socket(this.serverip, port);
                this.socket.setTcpNoDelay(true);
                this.socket.setSoLinger(true, 1);
                this.socket.setSoTimeout(0);
                this.socket.setKeepAlive(false);
                this.socket.setReceiveBufferSize(10240);
                ret = true;
                this.log.info("[connect to server ok port]: " + this.socket.getLocalPort());
                this.isConnected = true;
            }
        } catch (Exception ex) {
            ret = false;
            this.log.info("[connect to server error]:\r\n" + ex.getMessage());
        } finally {
            this.unFairLock.unlock();
        }
        return ret;
    }

    public synchronized boolean sendMessage(String msg) {
        boolean result = false;
        try {
            this.out.write(msg.getBytes());
            this.out.flush();
            result = true;
        } catch (IOException e) {
            this.log.error("socket is error! ", e);
            try {
                this.socket = null;
                this.in.close();
                this.in = null;
                this.out.close();
                this.out = null;
            } catch (Exception localException4) {
            }
        }

        return result;
    }

    public synchronized ResultData getMessage(String reqid) {
        ResultData rsData = null;
        if (this.isConnected) {
            try {
                long systemLong = System.currentTimeMillis();
                while (!this.isShutdown) {
                    if (System.currentTimeMillis() - systemLong > 10000L) {
                        return null;
                    }
                    String header = null;
                    String content = null;

                    header = readHeader(this.in);
                    String[] headers = header.split(",");
                    int len = Integer.parseInt(headers[0]);
                    content = readBody(this.in, len);
                    if (headers[1].equals(reqid)) {
                        rsData = new ResultData();
                        rsData.setContent(content);
                        rsData.setHeader(header);
                        return rsData;
                    }

                }

            } catch (Exception e) {
                this.log.error("socket is error! ", e);
                try {
                    this.socket = null;
                    this.in.close();
                    this.in = null;
                    this.out.close();
                    this.out = null;
                } catch (Exception localException1) {
                }
            }
        } else {
            this.log.error("user is not login!");
        }
        return null;
    }

    private String readHeader(InputStream is) {
        ByteArrayOutputStream buff = new ByteArrayOutputStream();
        try {
            while (!this.isShutdown) {
                byte b = (byte) is.read();
                if (b != -1) {
                    buff.write(b);
                    if (b == 10)
                        return new String(buff.toByteArray(), "UTF-8");
                }
            }
        } catch (Exception e) {
            this.log.error("ReadHeader exception " + e.getMessage());
            return null;
        }
        return null;
    }

    private String readBody(DataInputStream is, int limit) throws Exception {
        String ret = null;
        byte[] buff = new byte[limit];
        is.readFully(buff);
        ret = new String(buff, "utf-8");
        return ret;
    }

    public void close() {
        this.isConnected = false;
        this.isShutdown = true;
    }

    public void start(String ip, String port) {
        this.serverip = ip;
        this.serverport = port;
        CheckConn checkConn = new CheckConn(this);
        checkConn.start();
    }

    class CheckConn extends Thread {
        private ConnManager client;

        public CheckConn(ConnManager client) {
            this.client = client;
        }

        public void run() {
            while (!ConnManager.this.isShutdown)
                try {
                    if (ConnManager.this.socket == null) {
                        if (!ConnManager.this.connect()) {
                            ConnManager.this.isConnected = false;
                        } else {
                            ConnManager.this.in = new DataInputStream(ConnManager.this.socket.getInputStream());
                            ConnManager.this.out = new DataOutputStream(ConnManager.this.socket.getOutputStream());
                            String sendLoginStr = NssSenderManager.sendLoginStr(Configure.getToken());
                            ConnManager.this.sendMessage(sendLoginStr);
                            try {
                                while (!ConnManager.this.isShutdown) {
                                    String header = null;
                                    String content = null;

                                    header = ConnManager.this.readHeader(ConnManager.this.in);
                                    String[] headers = header.split(",");
                                    int len = Integer.parseInt(headers[0]);
                                    content = ConnManager.this.readBody(ConnManager.this.in, len);
                                    if ((headers[1].equals("0")) || (!headers[1].equals("8")))
                                        continue;
                                    if (content.trim().equals("0")) {
                                        ConnManager.this.log.info("login to server sucess");
                                        ConnManager.this.isConnected = true;
                                    } else if (content.trim().equals("1")) {
                                        ConnManager.this.log.info("login to server fail");
                                        ConnManager.this.isConnected = false;
                                        Thread.sleep(ConnManager.this.interval);
                                    }
                                }
                            } catch (RuntimeException e) {
                                ConnManager.this.log.error(e.getMessage(), e);
                            } catch (Exception e) {
                                ConnManager.this.log.error("socket is error! ", e);
                            }
                        }
                    }
                    Thread.sleep(ConnManager.this.interval);
                } catch (Exception e) {
                    ConnManager.this.log.error("heartbeat is error!", e);
                }
        }
    }
}